<template>
  <div class="toolbar-column-setting">
    <el-popover :show-arrow="false"
                :width="200"
                placement="bottom"
                popper-class="columns-setting-popover"
                trigger="click">
      <div class="column-setting">
        <div class="column-setting-title">
          <span class="label">列展示</span>
          <el-button link type="primary" @click="reset">重置</el-button>
        </div>
        <el-divider/>
        <el-scrollbar class="column-setting-content" max-height="420px">
          <Draggable v-model="draggableList" animation="300" handle=".mover" item-key="prop">
            <template #item="{ element: item, index }">
              <div v-if="item.type !== 'selection'" class="column-setting-item">
                <div class="column-handle">
                  <i class="icon mover">
                    <SvgIcon icon="drag-outlined"/>
                  </i>
                  <el-checkbox v-model="item.checked" :name="item.prop" @change="checkChange(item)"/>
                  <el-text line-clamp="1"> {{ item.label }}</el-text>
                </div>
                <div class="column-fixed">
                  <el-tooltip content="固定在左侧" placement="top">
                    <i :class="{ active: item.fixed === 'left' }" class="icon" @click="handleFixed(item, 'left')">
                      <SvgIcon icon="vertical-right-outlined"/>
                    </i>
                  </el-tooltip>
                  <el-tooltip content="固定在右侧" placement="top">
                    <i :class="{ active: item.fixed === 'right' }" class="icon" @click="handleFixed(item, 'right')">
                      <SvgIcon icon="vertical-left-outlined"/>
                    </i>
                  </el-tooltip>
                </div>
              </div>
            </template>
          </Draggable>
        </el-scrollbar>
      </div>
      <template #reference>
        <slot/>
      </template>
    </el-popover>
  </div>
</template>

<script lang="ts" setup>
import { computed, ref, watch } from 'vue';
import Draggable from '@/components/vuedraggable/src/vuedraggable';
import { isEmpty } from '@/utils/util';
import type { TableColumnData } from '@/components/table-column/index.vue';
import { SvgIcon } from '@/components/icon';

const mode = defineModel<TableColumnData[]>('columns');
const columnOptions = ref<TableColumnData[]>([]);
let columnSort: Record<string, number> = {};
let initValue: TableColumnData[] = [];
let initSort = {};

const draggableList = computed({
  get() {
    return columnOptions.value;
  },
  set(val) {
    columnOptions.value = val;
    // 更新setSort的排序值
    let tmpSorts = Object.values(columnSort).sort((a, b) => a - b);
    for (let i = 0; i < columnOptions.value.length; i++) {
      const item = columnOptions.value[i];
      const key = getSortKey(item);
      columnSort[key] = tmpSorts[i];
    }
    handleSort();
  },
});

const cloneColumns = (list: TableColumnData[]) => {
  return list.map((item) => ({...item}));
};

const getSortKey = (item: TableColumnData) => {
  return item.prop || item.type;
};

const isSet = (item: TableColumnData) => {
  return !isEmpty(item.prop) && item.type !== 'selection';
};

const init = () => {
  initValue = cloneColumns(mode.value!);
  mode.value?.forEach((item, index) => {
    const sortKey = getSortKey(item);
    initSort[sortKey] = index;
    if (isSet(item)) {
      columnSort[sortKey] = index;
    }
  });
};

init();

watch(mode, () => {
    columnOptions.value = [];
    mode.value?.forEach((item) => {
      const {hidden, prop, label, type, fixed} = item;
      if (isSet(item)) {
        columnOptions.value.push({type, prop, label, fixed, checked: hidden !== true});
      }
    });
  },
  {immediate: true},
);

// =========================== 处理 =======================

const handleSort = () => {
  mode.value?.sort((a, b) => {
    let aKey = getSortKey(a);
    let bKey = getSortKey(b);
    let aIndex = isSet(a) ? columnSort[aKey] : initSort[aKey]
    let bIndex = isSet(b) ? columnSort[bKey] : initSort[bKey]
    return aIndex - bIndex;
  });
};

const handleFixed = (data, fixed) => {
  let type: string;
  // 已经激活的就删除掉
  if (data.fixed === fixed) {
    type = 'delete';
    delete data.fixed;
  } else {
    type = 'update';
    data.fixed = fixed;
  }

  if (mode.value) {
    for (let i = 0; i < mode.value.length; i++) {
      const item = mode.value[i];
      if (item.prop === data.prop) {
        // 已经激活的就删除掉
        if (type === 'delete') {
          delete item.fixed;
        } else {
          item.fixed = fixed;
        }
        break;
      }
    }
  }
};

const checkChange = ({checked, prop}) => {
  if (mode.value) {
    for (let i = 0; i < mode.value.length; i++) {
      const item = mode.value[i];
      if (item.prop === prop) {
        item.hidden = !checked;
        break;
      }
    }
  }
};

const reset = () => {
  mode.value = cloneColumns(initValue);
};
</script>

<style lang="scss">
.toolbar-column-setting {
  display: inline-flex;
}

.columns-setting-popover.el-popover {
  padding: 0;

  .column-setting {
    .column-setting-title {
      padding: 12px 8px 0 12px;
      display: flex;
      align-items: center;
      justify-content: space-between;

      .label {
        color: var(--el-text-color-primary);
        letter-spacing: 1px;
      }

      .el-button {
        padding: 0;
        height: auto;
      }
    }

    .el-divider {
      margin: 8px 0;
    }

    .column-setting-content {
      margin-bottom: 8px;

      .column-setting-item {
        padding: 7px 12px;
        align-items: center;
        display: flex;

        .icon {
          font-size: 15px;
        }

        .column-handle {
          flex: 1;
          display: flex;

          .mover {
            cursor: move;
            margin-right: 8px;
            font-size: 16px;
          }

          .el-checkbox {
            height: auto;
            margin-right: 5px;
          }
        }

        .column-fixed {
          flex-shrink: 0;
          display: flex;
          margin-left: 3px;

          .icon {
            cursor: pointer;

            &.active {
              color: var(--el-color-primary);
            }
          }
        }
      }
    }
  }
}
</style>
